<!DOCTYPE html>
<html class="has-navbar-fixed-top">
<head>
    <meta charset="utf-8">
<title>Java核心类 - wanzixin</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/outdated-browser/1.1.5/outdatedbrowser.min.css">


<link href="/Study/Java/zh-cn/Java%E6%A0%B8%E5%BF%83%E7%B1%BB/" rel="alternate" hreflang="en" />
    


<meta name="description" content="">





    <meta name="description" content="本节介绍Java核心类，包括字符串，StringBuilder，StringJoiner，包装类型，JavaBean，枚举，常用工具类。">
<meta property="og:type" content="article">
<meta property="og:title" content="Java核心类">
<meta property="og:url" content="https://wanzixin.github.io/Study/Java/zh-cn/Java%E6%A0%B8%E5%BF%83%E7%B1%BB/index.html">
<meta property="og:site_name" content="wanzixin">
<meta property="og:description" content="本节介绍Java核心类，包括字符串，StringBuilder，StringJoiner，包装类型，JavaBean，枚举，常用工具类。">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-04-24T01:35:57.000Z">
<meta property="article:modified_time" content="2021-05-30T13:32:03.077Z">
<meta property="article:author" content="wanzixin">
<meta name="twitter:card" content="summary">





<link rel="icon" href="/favicon.png">


<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Ovo|Source+Code+Pro">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">


<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/lightgallery/1.6.8/css/lightgallery.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/justifiedGallery/3.6.5/css/justifiedGallery.min.css">


<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/atom-one-light.min.css">


<link rel="stylesheet" href="/css/style.css">


<script defer src="//use.fontawesome.com/releases/v5.0.8/js/all.js"></script>


    
    
    
    
    
    
    
    
    
    

    


<meta name="generator" content="Hexo 5.4.0"></head>
<body>
    
<nav class="navbar is-transparent is-fixed-top navbar-main" role="navigation" aria-label="main navigation">
    <div class="container">
        <div class="navbar-brand">
            <a class="navbar-item navbar-logo" href="/zh-cn">
                
                    
                    wanzixin
                    
                
            </a>
            <div class="navbar-burger">
                <span></span>
                <span></span>
                <span></span>
            </div>
        </div>
        
        <div class="navbar-menu navbar-start">
            
            <a class="navbar-item "
               href="/archives">Archives</a>
            
            <a class="navbar-item "
               href="/categories">Categories</a>
            
            <a class="navbar-item "
               href="/categories/Diary">Diary</a>
            
            <a class="navbar-item "
               href="/categories/Gallery">Gallery</a>
            
            <a class="navbar-item "
               href="/categories/Study">Study</a>
            
            <a class="navbar-item "
               href="/categories/Item">Item</a>
            
            <a class="navbar-item "
               href="/about">About</a>
            
        </div>
        
        <div class="navbar-menu navbar-end">
            
            <a class="navbar-item search" title="搜索" href="javascript:;">
                <i class="fas fa-search"></i>
            </a>
            
            
            <div class="navbar-item is-hoverable has-dropdown is-hidden-mobile is-hidden-tablet-only toc">
                <a class="navbar-item" title="目录">
                    <i class="fa fa-list"></i>
                </a>
                <div class="navbar-dropdown is-right">
                    
                    
                    
                    
                    <a class="navbar-item" href="#字符串和编码">1&nbsp;&nbsp;<b>字符串和编码</b></a>
                    
                    
                    
                    <a class="navbar-item" href="#String">1.1&nbsp;&nbsp;String</a>
                    
                    
                    
                    <a class="navbar-item" href="#常用字符串操作">1.2&nbsp;&nbsp;常用字符串操作</a>
                    
                    
                    
                    <a class="navbar-item" href="#类型转换">1.3&nbsp;&nbsp;类型转换</a>
                    
                    
                    
                    <a class="navbar-item" href="#字符编码">1.4&nbsp;&nbsp;字符编码</a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#StringBuilder">2&nbsp;&nbsp;<b>StringBuilder</b></a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#StringJoiner">3&nbsp;&nbsp;<b>StringJoiner</b></a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#包装类型">4&nbsp;&nbsp;<b>包装类型</b></a>
                    
                    
                    
                    <a class="navbar-item" href="#自动装箱">4.1&nbsp;&nbsp;自动装箱</a>
                    
                    
                    
                    <a class="navbar-item" href="#不变类">4.2&nbsp;&nbsp;不变类</a>
                    
                    
                    
                    <a class="navbar-item" href="#进制转换">4.3&nbsp;&nbsp;进制转换</a>
                    
                    
                    
                    <a class="navbar-item" href="#处理无符号整型">4.4&nbsp;&nbsp;处理无符号整型</a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#JavaBean">5&nbsp;&nbsp;<b>JavaBean</b></a>
                    
                    
                    
                    <a class="navbar-item" href="#JavaBean的作用">5.1&nbsp;&nbsp;JavaBean的作用</a>
                    
                    
                    
                    <a class="navbar-item" href="#枚举JavaBean">5.2&nbsp;&nbsp;枚举JavaBean</a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#枚举类">6&nbsp;&nbsp;<b>枚举类</b></a>
                    
                    
                    
                    <a class="navbar-item" href="#enum的比较">6.1&nbsp;&nbsp;enum的比较</a>
                    
                    
                    
                    <a class="navbar-item" href="#enum类型">6.2&nbsp;&nbsp;enum类型</a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#纪录类">7&nbsp;&nbsp;<b>纪录类</b></a>
                    
                    
                    
                    <a class="navbar-item" href="#record">7.1&nbsp;&nbsp;record</a>
                    
                    
                    
                    <a class="navbar-item" href="#构造方法">7.2&nbsp;&nbsp;构造方法</a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#BigInteger">8&nbsp;&nbsp;<b>BigInteger</b></a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#BigDecimal">9&nbsp;&nbsp;<b>BigDecimal</b></a>
                    
                    
                    <hr class="navbar-divider">
                    
                    
                    <a class="navbar-item" href="#常用工具类">10&nbsp;&nbsp;<b>常用工具类</b></a>
                    
                    
                    
                    <a class="navbar-item" href="#Math">10.1&nbsp;&nbsp;Math</a>
                    
                    
                    
                    <a class="navbar-item" href="#Random">10.2&nbsp;&nbsp;Random</a>
                    
                    
                    
                    <a class="navbar-item" href="#SecureRandom">10.3&nbsp;&nbsp;SecureRandom</a>
                    
                </div>
            </div>
            
            
            <a class="navbar-item" title="GitHub" target="_blank" rel="noopener" href="https://github.com/wanzixin">
                
                <i class="fab fa-github"></i>
                
            </a>
               
            
        </div>
    </div>
</nav>

    <section class="section">
    <div class="container">
    <article class="article content gallery" itemscope itemprop="blogPost">
    <h1 class="article-title is-size-3 is-size-4-mobile" itemprop="name">
        
            Java核心类
        
    </h1>
    <div class="article-meta columns is-variable is-1 is-multiline is-mobile is-size-7-mobile">
        <span class="column is-narrow">
            
                <span>4月 24 2021</span>
            
        </span>
        
        <span class="column is-narrow article-category">
            <i class="far fa-folder"></i>
            <a class="article-category-link" href="/zh-cn/categories/Study/">Study</a><span>></span><a class="article-category-link" href="/zh-cn/categories/Study/Java/">Java</a>
        </span>
        
        
        <span class="column is-narrow">
            
            
            35 分钟 读完 (约 5244 字)
        </span>
        
    </div>
    <div class="article-entry is-size-6-mobile" itemprop="articleBody">
    
        <html><head></head><body><p>本节介绍Java核心类，包括字符串，StringBuilder，StringJoiner，包装类型，JavaBean，枚举，常用工具类。<span id="more"></span></p>
<h2 id="字符串和编码"><a href="#字符串和编码" class="headerlink" title="字符串和编码"></a>字符串和编码</h2><h3 id="String"><a href="#String" class="headerlink" title="String"></a>String</h3><p>在Java中，String是一个引用类型，它本身也是一个class。但是Java对String有特殊处理，可以直接用<code>"..."</code>来表示一个字符串。实际上字符串在String内部是通过一个<code>char[]</code>数组表示的。因为String太常用了，所以Java提供了这种字符串字面量的表示方法。</p>
<p>Java字符串的一个重要特点是<code>字符串不可变</code>。</p>
<p>当我们想要比较两个字符串是否相同时，我们实际上想比较字符串的内容是否相同。必须用<code>equals()</code>方法，而不能使用<code>==</code>。</p>
<p>要忽略大小写比较，使用<code>equalsIgnoreCase()</code>方法。</p>
<h3 id="常用字符串操作"><a href="#常用字符串操作" class="headerlink" title="常用字符串操作"></a>常用字符串操作</h3><p>提取字串、查找、替换、大小写转换等。</p>
<p>使用<code>trim()</code>方法可以移除字符串首尾空白字符。空白字符包括空格，<code>\t</code>，<code>\r</code>，<code>\n</code>。注意，trim()并没有改变字符串内容，而是返回了一个新字符串。另一个<code>strip()</code>方法也可以移除字符串首尾空白字符。它和<code>trim()</code>不同的是，类似中文的空格字符<code>\u3000</code>也会被移除。</p>
<p> <code>isEmpty()</code>和<code>isBlank()</code>来判断字符串是否为空和空白字符串。</p>
<p>有几个占位符，后面就传入几个参数。参数类型要和占位符一致。我们经常用这个方法来格式化信息。常用的占位符有：</p>
<ul>
<li><code>%s</code>：显示字符串；</li>
<li><code>%d</code>：显示整数；</li>
<li><code>%x</code>：显示十六进制整数；</li>
<li><code>%f</code>：显示浮点数。</li>
</ul>
<h3 id="类型转换"><a href="#类型转换" class="headerlink" title="类型转换"></a>类型转换</h3><p>要把任意基本类型或引用类型转换为字符串，可以使用静态方法<code>valueOf()</code>。 这是一个重载方法，编译器会根据参数自动选择合适的方法。要把字符串转换为其他类型，就需要根据情况。 </p>
<p><code>String</code>和<code>char[]</code>类型可以互相转换。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">char</span>[] cs = <span class="hljs-string">"Hello"</span>.toCharArray(); <span class="hljs-comment">// String -&gt; char[]</span><br>String s = <span class="hljs-keyword">new</span> String(cs); <span class="hljs-comment">// char[] -&gt; String</span><br></code></pre></td></tr></tbody></table></figure>

<p>从<code>String</code>的不变性设计可以看出，如果传入的对象有可能改变，我们需要复制而不是直接引用。</p>
<h3 id="字符编码"><a href="#字符编码" class="headerlink" title="字符编码"></a>字符编码</h3><p>在早期的计算机系统中，为了给字符编码，美国国家标准学会（American National Standard Institute：ANSI）制定了一套英文字母、数字和常用符号的编码，它占用一个字节，编码范围从<code>0</code>到<code>127</code>，最高位始终为<code>0</code>，称为<code>ASCII</code>编码。</p>
<p>类似的， <code>GB2312</code>标准使用两个字节表示一个汉字，日文有<code>Shift_JIS</code>编码，韩文有<code>EUC-KR</code>编码，这些编码因为标准不统一，同时使用，就会产生冲突。 </p>
<p>为了统一全球所有语言的编码，全球统一码联盟发布了<code>Unicode</code>编码，它把世界上主要语言都纳入同一个编码，这样，中文、日文、韩文和其他语言就不会冲突。 </p>
<p>那我们经常使用的<code>UTF-8</code>又是什么编码呢？因为英文字符的<code>Unicode</code>编码高字节总是<code>00</code>，包含大量英文的文本会浪费空间，所以，出现了<code>UTF-8</code>编码，它是一种变长编码，用来把固定长度的<code>Unicode</code>编码变成1～4字节的变长编码。 <code>UTF-8</code>编码的另一个好处是容错能力强。如果传输过程中某些字符出错，不会影响后续字符，因为<code>UTF-8</code>编码依靠高字节位来确定一个字符究竟是几个字节，它经常用来作为传输编码。 </p>
<h2 id="StringBuilder"><a href="#StringBuilder" class="headerlink" title="StringBuilder"></a>StringBuilder</h2><p>Java编译器对String做了特殊处理，使得我们可以直接用<code>+</code>拼接字符串。String在拼接时总会创建新的字符串对象，然后扔掉旧的字符串。这样，绝大多数字符串都是临时对象，不但浪费内存，还影响GC效率。</p>
<p>为了能高效拼接字符串，Java标准库提供了<code>StringBuilder</code>，它是一个可变对象，可以预分配缓冲区。这样，往StringBuilder中新增字符时，不会创建新的临时对象。</p>
<p>StringBuilder还可以进行链式操作。</p>
<p>注意：对于普通字符串<code>+</code>操作，并不需要我们将其改写为StringBuilder，因为Java编译器在编译时就自动把多个连续的<code>+</code>操作编码为<code>StringConcatFactory</code>的操作。在运行期，StringConcatFactory会自动把字符串连接优化为数组复制或者StringBuilder操作。</p>
<p>你可能还听说过<code>StringBuffer</code>，这是Java早期的一个StringBuilder的线程安全版本，它通过同步来保证多个线程操作StringBuffer是安全的，但是同步会带来执行速度的下降。</p>
<h2 id="StringJoiner"><a href="#StringJoiner" class="headerlink" title="StringJoiner"></a>StringJoiner</h2><p>用分隔符拼接数组的需求很常见，Java标准库提供了一个<code>StringJoiner</code>来干这个事。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java">String[] names = {<span class="hljs-string">"Bob"</span>, <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"Grace"</span>};<br><span class="hljs-keyword">var</span> sj = <span class="hljs-keyword">new</span> StringJoiner(<span class="hljs-string">", "</span>, <span class="hljs-string">"Hello "</span>, <span class="hljs-string">"!"</span>);<br><span class="hljs-keyword">for</span> (String name : names) {<br>	sj.add(name);<br>}<span class="hljs-comment">//hello和!分别是开头和结尾</span><br></code></pre></td></tr></tbody></table></figure>

<p>String还提供了一个静态方法<code>join()</code>，这个方法在内部使用了StringJoiner来拼接字符串，在不需要指定开头和结尾时，用<code>String.join()</code>更方便。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">String[] names = {<span class="hljs-string">"Bob"</span>, <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"Grace"</span>};<br><span class="hljs-keyword">var</span> s = String.join(<span class="hljs-string">", "</span>, names);<br></code></pre></td></tr></tbody></table></figure>

<h2 id="包装类型"><a href="#包装类型" class="headerlink" title="包装类型"></a>包装类型</h2><p>我们已经知道，Java的数据类型分两种：</p>
<p>基本类型：byte，short，int，long，boolean，float，double，char</p>
<p>引用类型：所有class和interface类型</p>
<p>引用类型可以赋值为<code>null</code>表示空，但基本类型不能赋值为null。</p>
<p>那么如何把一个基本类型视为对象（引用类型）呢？</p>
<p>比如，我们想要把int基本类型变成一个引用类型，我们可以定义一个<code>Interger</code>，它只包含一个int型的实例字段，这样就把Integer视为int的包装类型（Wrapper Class）。定义好了Interger，就可以把int和Interger相互转换。</p>
<p>实际上，因为包装类型非常有用，Java核心库为每种基本类型都提供了对应的包装类型。</p>
<h3 id="自动装箱"><a href="#自动装箱" class="headerlink" title="自动装箱"></a>自动装箱</h3><p>Java编译器可以帮助我们自动在int和Interger之间转型。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">Integer n = <span class="hljs-number">100</span>; <span class="hljs-comment">// 编译器自动使用Integer.valueOf(int)</span><br><span class="hljs-keyword">int</span> x = n; <span class="hljs-comment">// 编译器自动使用Integer.intValue()</span><br></code></pre></td></tr></tbody></table></figure>

<p>这种直接把int变为Interger的赋值写法，成为自动装箱（Auto Boxing），反过来，把Interger变为int的赋值写法，成为自动拆箱（Auto Unboxing）。</p>
<p>注意：自动装箱和自动拆箱只发生在编译阶段，目的是为了少写代码。装箱和拆箱会影响代码的执行效率，因为编译后的class代码是严格区分基本类型和引用类型的。并且，自动拆箱执行时可能会报<code>NullPointerException</code>。</p>
<h3 id="不变类"><a href="#不变类" class="headerlink" title="不变类"></a>不变类</h3><p>所有的包装类型都是不变类。因此一旦创建了Interger对象，该对象就是不变的。对两个Interger实例进行比较时要特别注意，绝不能用<code>==</code>比较，因为Interger是引用类型，必须用<code>equals()</code>比较。</p>
<p>在我们自己创建Interger的时候，有以下两种方法：</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">Interger n = <span class="hljs-keyword">new</span> Interger(<span class="hljs-number">100</span>);<span class="hljs-comment">//方法一</span><br>Interger n = interger.valueOf(<span class="hljs-number">100</span>);<span class="hljs-comment">//方法二</span><br></code></pre></td></tr></tbody></table></figure>

<p>方法二更好，因为方法一总是创建新的Interger实例，方法二把内部优化交给Interger的实现者来做，即使在当前版本没有优化，也有可能在下一个版本进行优化。</p>
<p>我们把能创建”新“对象的静态方法称为静态工厂方法。<code>Interger.valueOf()</code>就是静态工厂方法，它尽可能的返回缓存的实例以节省内存。</p>
<h3 id="进制转换"><a href="#进制转换" class="headerlink" title="进制转换"></a>进制转换</h3><p>Interger类本身还提供了大量方法，例如，最常用的静态方法<code>parseint()</code>可以把字符串解析成一个整数。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">int</span> x1 = Integer.parseInt(<span class="hljs-string">"100"</span>); <span class="hljs-comment">// 100</span><br><span class="hljs-keyword">int</span> x2 = Integer.parseInt(<span class="hljs-string">"100"</span>, <span class="hljs-number">16</span>); <span class="hljs-comment">// 256,因为按16进制解析</span><br></code></pre></td></tr></tbody></table></figure>

<p>Integer还可以把整数格式化为指定进制的字符串。</p>
<p>Java的包装类型还定义了一些有用的静态变量。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// boolean只有两个值true/false，其包装类型只需要引用Boolean提供的静态字段:</span><br>Boolean t = Boolean.TRUE;<br>Boolean f = Boolean.FALSE;<br><span class="hljs-comment">// int可表示的最大/最小值:</span><br><span class="hljs-keyword">int</span> max = Integer.MAX_VALUE; <span class="hljs-comment">// 2147483647</span><br><span class="hljs-keyword">int</span> min = Integer.MIN_VALUE; <span class="hljs-comment">// -2147483648</span><br><span class="hljs-comment">// long类型占用的bit和byte数量:</span><br><span class="hljs-keyword">int</span> sizeOfLong = Long.SIZE; <span class="hljs-comment">// 64 (bits)</span><br><span class="hljs-keyword">int</span> bytesOfLong = Long.BYTES; <span class="hljs-comment">// 8 (bytes)</span><br></code></pre></td></tr></tbody></table></figure>

<p>最后，所有的整数和浮点数的包装类型都继承自<code>Number</code>，因此可以非常方便的通过包装类型获取各种基本类型。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 向上转型为Number:</span><br>Number num = <span class="hljs-keyword">new</span> Integer(<span class="hljs-number">999</span>);<br><span class="hljs-comment">// 获取byte, int, long, float, double:</span><br><span class="hljs-keyword">byte</span> b = num.byteValue();<br><span class="hljs-keyword">int</span> n = num.intValue();<br><span class="hljs-keyword">long</span> ln = num.longValue();<br><span class="hljs-keyword">float</span> f = num.floatValue();<br><span class="hljs-keyword">double</span> d = num.doubleValue();<br></code></pre></td></tr></tbody></table></figure>

<h3 id="处理无符号整型"><a href="#处理无符号整型" class="headerlink" title="处理无符号整型"></a>处理无符号整型</h3><p>在Java中，并没有无符号整型（Unsigned）的基本数据类型。byte，short，int和long都是带符号整型，最高位是符号位。无符号整型和有符号整型的转换在Java中就需要借助包装类型的静态方法完成。例如：</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">byte</span> x = -<span class="hljs-number">1</span>;<br><span class="hljs-keyword">byte</span> y = Byte.toUnsignedInt(x);<br></code></pre></td></tr></tbody></table></figure>

<h2 id="JavaBean"><a href="#JavaBean" class="headerlink" title="JavaBean"></a>JavaBean</h2><p>在Java中，有很多class都符合这样的规范：</p>
<ul>
<li>若干private实例字段</li>
<li>通过public方法来读写实例字段</li>
</ul>
<p>如果读写方法符合以下这种命名规范：</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//读方法</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> Type <span class="hljs-title">getXyz</span><span class="hljs-params">()</span></span>;<br><span class="hljs-comment">//写方法</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setXyz</span><span class="hljs-params">(Type value)</span></span>;<br></code></pre></td></tr></tbody></table></figure>

<p>那么这种class被称为<code>JavaBean</code>。</p>
<p>上面的字段是xyz，那么读写方法分别以get和set开头，并且后接大写字母开头的字段名Xyz，因此读写方法分别是getXyz()和setXyz()。boolean字段比较特殊，它的读方法一般命名为isXyz()。</p>
<p>我们通常把一组对应的读方法（<code>getter</code>）和写方法（<code>setter</code>）称为属性（<code>property</code>）。只有getter的属性称为只读属性。</p>
<p>属性只需要定义getter和setter方法，不一定需要对应字段。可以看出，getter和setter也是一种数据封装的方法。</p>
<h3 id="JavaBean的作用"><a href="#JavaBean的作用" class="headerlink" title="JavaBean的作用"></a>JavaBean的作用</h3><p>JavaBean主要用来传递数据，即把一组数据组合一个JavaBean便于传输。此外，JavaBean可以方便地被IDE分析，生成读写属性的代码，主要用在图形界面的可视化设计中。</p>
<h3 id="枚举JavaBean"><a href="#枚举JavaBean" class="headerlink" title="枚举JavaBean"></a>枚举JavaBean</h3><p>要枚举一个JavaBean的所有属性，可以直接使用Java核心库提供的<code>Introspector</code>。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">BeanInfo info = Introspector.getBeanInfo(Person.class);<br><span class="hljs-keyword">for</span> (PropertyDescriptor pd : info.getPropertyDescriptors()) {<br>    System.out.println(pd.getName());<br>    System.out.println(<span class="hljs-string">"  "</span> + pd.getReadMethod());<br>    System.out.println(<span class="hljs-string">"  "</span> + pd.getWriteMethod());<br>}<br></code></pre></td></tr></tbody></table></figure>

<h2 id="枚举类"><a href="#枚举类" class="headerlink" title="枚举类"></a>枚举类</h2><p>为了让编译器能自动检查某个值在枚举的集合内，并且不同用途的枚举需要不同的类型来标记，不能混用，我们可以使用<code>enum</code>来定义枚举类。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Weekday</span> </span>{<br>    SUN, MON, TUE, WED, THU, FRI, SAT;<br>}<br></code></pre></td></tr></tbody></table></figure>

<p>注意到定义枚举类是通过关键字enum实现的，我们只需要依次列举出枚举的常量名。和int定义的常量相比，使用enum定义枚举有如下好处：</p>
<p>首先，enum常量本身带有类型信息，即Weekday.SUN类型是Weekday，编译器会自动检查出类型错误。其次，不可能引用到非枚举的值，因为无法通过编译。最后，不同类型的枚举不能相互比较或者赋值，因为类型不符。这就使得编译器可以在编译器自动检查出所有可能的潜在错误。</p>
<h3 id="enum的比较"><a href="#enum的比较" class="headerlink" title="enum的比较"></a>enum的比较</h3><p>使用enum定义的枚举类型是引用类型。引用类型比较，要使用equals()方法，如果使用==比较，它比较的是两个引用类型的变量是否是同一个对象。因此，引用类型比较，要始终使用equals()方法，但enum类型可以例外。 </p>
<p>因为enum类型的每个常量在JVM中只有一个唯一实例，所以可以直接用==比较。</p>
<h3 id="enum类型"><a href="#enum类型" class="headerlink" title="enum类型"></a>enum类型</h3><p>通过enum定义的枚举类，和其他class有什么区别？答案是没有任何区别。enum定义的类型就是class，只不过它有以及几个特点。</p>
<ul>
<li>定义的enum类型总是继承自java.lang.Enum，且无法被继承</li>
<li>只能定义出enum实例，而无法通过new操作符创建enum实例</li>
<li>定义的每个实例都是引用类型的唯一实例</li>
<li>可以将enum类型用于switch语句</li>
</ul>
<p>因为enum是一个class，每个枚举的值都是class实例，这些实例有一些方法。</p>
<ul>
<li>name() 返回常量名</li>
<li>ordinal() 返回定义的常量的顺序，从0开始计数</li>
</ul>
<p>对枚举常量调用toString()会返回和name()一样的字符串。但是，toString()可以被覆写，而name()则不行。覆写toString()的目的是在输出时更有可读性。</p>
<h2 id="纪录类"><a href="#纪录类" class="headerlink" title="纪录类"></a>纪录类</h2><p>使用String，Integer等类型的时候，这些类型都是不变类，一个不变类具有以下几个特点：</p>
<ul>
<li>定义class时使用final，无法派生子类</li>
<li>每个字段使用final，保证创建实例后无法修改任何字段</li>
</ul>
<p>为了保证不变类的比较，还需要正确覆写equals()和hashCode()，这样才能在集合类中正常使用。</p>
<h3 id="record"><a href="#record" class="headerlink" title="record"></a>record</h3><p>从Java 14开始，引入了新的Record类。我们定义Record类时，使用关键字<code>record</code>。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Point</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{}<br><br><span class="hljs-comment">//改写为class</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Record</span> </span>{<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> x;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> y;<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Point</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{<br>        <span class="hljs-keyword">this</span>.x = x;<br>        <span class="hljs-keyword">this</span>.y = y;<br>    }<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">x</span><span class="hljs-params">()</span> </span>{<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.x;<br>    }<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">y</span><span class="hljs-params">()</span> </span>{<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.y;<br>    }<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{<br>        <span class="hljs-keyword">return</span> String.format(<span class="hljs-string">"Point[x=%s, y=%s]"</span>, x, y);<br>    }<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object o)</span> </span>{<br>        ...<br>    }<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span> </span>{<br>        ...<br>    }<br>}<br></code></pre></td></tr></tbody></table></figure>

<p>除了用final修饰class以及每个字段外，编译器还为我们创建了构造方法，和字段名同名的方法，以及覆写toString()，equals()和hashCode()方法。换句话说，使用record关键字可以一行写出一个不变类。</p>
<p>和enum类似，我们自己不能直接从Record派生，只能通过record关键字由编译器实现继承。</p>
<h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><p>编译器默认按照record声明的变量顺序自动创建一个构造方法，并在方法内给字段赋值。那么问题来了，如果我们要检查参数，应该怎么办？</p>
<p>假设Point类的x，y不允许负数，我们就给Point的构造函数加上检查逻辑。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Point</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{<br>    <span class="hljs-keyword">public</span> Point {<br>        <span class="hljs-keyword">if</span> (x &lt; <span class="hljs-number">0</span> || y &lt; <span class="hljs-number">0</span>) {<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException();<br>        }<br>    }<br>}<br></code></pre></td></tr></tbody></table></figure>

<p>注意到方法<code>public Point{...}</code>被称为Compact Constructor，它的目的是让我们编写出检查逻辑，编译器最终生成的构造方法如下：</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Record</span> </span>{<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Point</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{<br>        <span class="hljs-comment">// 这是我们编写的Compact Constructor:</span><br>        <span class="hljs-keyword">if</span> (x &lt; <span class="hljs-number">0</span> || y &lt; <span class="hljs-number">0</span>) {<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException();<br>        }<br>        <span class="hljs-comment">// 这是编译器继续生成的赋值代码:</span><br>        <span class="hljs-keyword">this</span>.x = x;<br>        <span class="hljs-keyword">this</span>.y = y;<br>    }<br>    ...<br>}<br></code></pre></td></tr></tbody></table></figure>

<p>作为record的Point仍然可以添加静态方法，一般常用的静态的<code>of()</code>方法，用来创建Point。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Point</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Point <span class="hljs-title">of</span><span class="hljs-params">()</span> </span>{<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Point(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>);<br>    }<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Point <span class="hljs-title">of</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Point(x, y);<br>    }<br>}<br></code></pre></td></tr></tbody></table></figure>

<p>这样我们可以写出更简洁的代码。</p>
<figure class="highlight java hljs"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">var</span> z = Point.of();<br><span class="hljs-keyword">var</span> p = Point.of(<span class="hljs-number">123</span>, <span class="hljs-number">456</span>);<br></code></pre></td></tr></tbody></table></figure>

<h2 id="BigInteger"><a href="#BigInteger" class="headerlink" title="BigInteger"></a>BigInteger</h2><p>在Java中，由CPU原生提供的整型最大范围是64位long型整数。使用long型整数可以直接通过CPU指令进行计算，速度非常快。</p>
<p>如果我们使用的整数范围超过了long型怎么办？这时，就只能用软件来模拟一个大整数。<code>java.math.BigInteger</code>就是用来表示任意大小的整数。BigInteger内部使用一个int[]数组来模拟一个非常大的整数。</p>
<p>和long型整数运算相比，BigInteger不会有范围限制，但缺点是速度比较慢。</p>
<p>Biginteger和Integer、Long一样，也是不变类，也继承自Number类，因为Number定义了几种转换为基本类型的几个方法：</p>
<ul>
<li>转换为byte：byteValue()</li>
<li>转换为short：shortValue()</li>
<li>转换为int：intValue()</li>
<li>转换为long：longValue()</li>
<li>转换为float：floatValue()</li>
<li>转换为double：doubleValue()</li>
</ul>
<p>因此，通过上述方法，可以把BigInteger转换为基本类型。如果BigInteger表示的范围超过了基本类型的范围，转换时将丢失高位信息，即结果不一定是准确的。如果需要准确的转换成基本类型，可以使用intValueExact()、longValueExact()等方法，在转换时如果超出范围，将直接抛出<code>ArithmeticException</code>异常。</p>
<h2 id="BigDecimal"><a href="#BigDecimal" class="headerlink" title="BigDecimal"></a>BigDecimal</h2><p>和BigInteger类似，BigDecimal可以表示一个任意大小且精度完全准确的浮点数。</p>
<p>BigDecimal用scale()表示小数位数。如果一个BigDecimal的scale()返回负数，例如返回-2，表示这个数是整数，并且末尾有两个0。可以对一个BigDecimal设置scale，如果精度比原始值低，那么按照指定的方法进行四舍五入或者直接截断。</p>
<p>stripTrailingZeros()可以将一个BigDecimal格式化为一个相等的，但去掉了末尾0的BigDecimal。</p>
<p>对BigDecimal做加减乘，精度不会丢失，但是做除法时，存在除不尽的情况，这时必须指定精度以及如何截断。</p>
<p>比较BigDecimal</p>
<p>在比较两个BigDecimal的值是否相等时，要特别注意，使用equals()方法不但要求两个BigDecimal值相等，还要求他们的scale()相等。使用compareTo()方法来比较，它根据两个值的大小分别返回负数、正数和0，分别表示小于，大于和等于。</p>
<p>BigDecimal也是从Number继承的，也是不可变对象。</p>
<h2 id="常用工具类"><a href="#常用工具类" class="headerlink" title="常用工具类"></a>常用工具类</h2><p>Java的核心库提供了大量的现成的类供我们使用。</p>
<h3 id="Math"><a href="#Math" class="headerlink" title="Math"></a>Math</h3><p>Math类是用来进行数学计算的，它提供了大量的静态方法来便于我们实现数学计算。</p>
<p>求绝对值，最值，计算x^y次方，e^x，以e为低的对数，三角函数，几个数学常量，生成随机数等等。</p>
<h3 id="Random"><a href="#Random" class="headerlink" title="Random"></a>Random</h3><p><code>Random</code>用来创建伪随机数。所谓伪随机数，是指只要给定一个初始的种子，产生的随机数序列是完全一样的。</p>
<p>要生成一个随机数，可以使用<code>nextInt()</code>、<code>nextLong()</code>、<code>nextFloat()</code>、<code>nextDouble()</code>。</p>
<p>我们在创建Random实例时，如果不给定种子，就使用系统当前时间戳作为种子，因此每次运行时，种子不同得到的随机数序列也就不同。如果我们创建Random实例时指定一个种子，就会得到完全相同的随机数序列。</p>
<h3 id="SecureRandom"><a href="#SecureRandom" class="headerlink" title="SecureRandom"></a>SecureRandom</h3><p>有伪随机数，就有真随机数。实际上真正的真随机数只能通过量子力学原理来获取，而我们想要的是一个不可预测的安全的随机数，SecureRandom就是用来创建安全的随机数的。</p>
<blockquote>
<p><code>SecureRandom</code>无法指定种子，它使用RNG（random number generator）算法。JDK的<code>SecureRandom</code>实际上有多种不同的底层实现，有的使用安全随机种子加上伪随机数算法来产生安全的随机数，有的使用真正的随机数生成器。实际使用的时候，可以优先获取高强度的安全随机数生成器，如果没有提供，再使用普通等级的安全随机数生成器： </p>
<p><code>SecureRandom</code>的安全性是通过操作系统提供的安全的随机种子来生成随机数。这个种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”。</p>
<p>在密码学中，安全的随机数非常重要。如果使用不安全的伪随机数，所有加密体系都将被攻破。因此，时刻牢记必须使用<code>SecureRandom</code>来产生安全的随机数。</p>
</blockquote>
</body></html>
    
    </div>
    
    
    <div class="columns is-mobile is-multiline article-nav">
        <span class="column is-12-mobile is-half-desktop  article-nav-prev">
            
            <a href="/Study/Java/zh-cn/%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86/">异常处理</a>
            
        </span>
        <span class="column is-12-mobile is-half-desktop  article-nav-next">
            
            <a href="/Study/Java/zh-cn/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%9F%BA%E7%A1%80/">面向对象基础</a>
            
        </span>
    </div>
    
</article>


<div class="sharebox">
    
<div class="sharethis-inline-share-buttons"></div>
<script type='text/javascript' src='//platform-api.sharethis.com/js/sharethis.js#property=608c1408daac690012507aa2&amp;product=sop' async='async'></script>

</div>



    </div>
</section>
    <footer class="footer">
    <div class="container">
        <div class="columns content">
            <div class="column is-narrow has-text-centered">
                &copy; 2021 wanzixin&nbsp;
                Powered by <a href="http://hexo.io/" target="_blank">Hexo</a> & <a
                        target="_blank" rel="noopener" href="http://github.com/ppoffice/hexo-theme-minos">Minos</a>
            </div>
            <div class="column is-hidden-mobile"></div>

            
            <div class="column is-narrow">
                <div class="columns is-mobile is-multiline is-centered">
                
                    
                <a class="column is-narrow has-text-black" title="GitHub" target="_blank" rel="noopener" href="https://github.com/ppoffice/hexo-theme-minos">
                    
                    GitHub
                    
                </a>
                
                </div>
            </div>
            
            
<div class="column is-narrow has-text-centered">
    <div class="dropdown is-up is-right is-hoverable" style="margin-top: -0.2em;">
        <div class="dropdown-trigger">
            <button class="button is-small" aria-haspopup="true" aria-controls="dropdown-menu7">
                <span class="icon">
                    <i class="fas fa-globe"></i>
                </span>
                <span>简体中文</span>
                <span class="icon is-small">
            <i class="fas fa-angle-down" aria-hidden="true"></i>
          </span>
            </button>
        </div>
        <div class="dropdown-menu has-text-left" role="menu">
            <div class="dropdown-content">
            
                <a href="/Study/Java/zh-cn/Java%E6%A0%B8%E5%BF%83%E7%B1%BB/" class="dropdown-item">
                    English
                </a>
            
                <a href="/zh-cn/Study/Java/zh-cn/Java%E6%A0%B8%E5%BF%83%E7%B1%BB/" class="dropdown-item">
                    简体中文
                </a>
            
            </div>
        </div>
    </div>
</div>

        </div>
    </div>
</footer>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment-with-locales.min.js"></script>

<!-- test if the browser is outdated -->
<div id="outdated">
    <h6>Your browser is out-of-date!</h6>
    <p>Update your browser to view this website correctly. <a id="btnUpdateBrowser" target="_blank" rel="noopener" href="http://outdatedbrowser.com/">Update my browser now </a></p>
    <p class="last"><a href="#" id="btnCloseUpdateBrowser" title="Close">&times;</a></p>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/outdated-browser/1.1.5/outdatedbrowser.min.js"></script>
<script>
    $(document).ready(function () {
        // plugin function, place inside DOM ready function
        outdatedBrowser({
            bgColor: '#f25648',
            color: '#ffffff',
            lowerThan: 'flex'
        })
    });
</script>

<script>
    window.FontAwesomeConfig = {
        searchPseudoElements: true
    }
    moment.locale("zh-CN");
</script>


    
    
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML"></script>
<script>
    MathJax.Hub.Config({
        "HTML-CSS": {
            matchFontHeight: false
        },
        SVG: {
            matchFontHeight: false
        },
        CommonHTML: {
            matchFontHeight: false
        },
        tex2jax: {
            inlineMath: [
                ['$','$'],
                ['\\(','\\)']
            ]
        }
    });
</script>

    
    
    
    
<script src="//cdnjs.cloudflare.com/ajax/libs/lightgallery/1.6.8/js/lightgallery-all.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/justifiedGallery/3.6.5/js/jquery.justifiedGallery.min.js"></script>
<script>
    (function ($) {
        $(document).ready(function () {
            if (typeof($.fn.lightGallery) === 'function') {
                $('.article.gallery').lightGallery({ selector: '.gallery-item' });
            }
            if (typeof($.fn.justifiedGallery) === 'function') {
                $('.justified-gallery').justifiedGallery();
            }
        });
    })(jQuery);
</script>

    
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js"></script>
    <style>
        .hljs {
            position: relative;
        }

        .hljs .clipboard-btn {
            float: right;
            color: #9a9a9a;
            background: none;
            border: none;
            cursor: pointer;
        }

        .hljs .clipboard-btn:hover {
          color: #8a8a8a;
        }

        .hljs > .clipboard-btn {
            display: none;
            position: absolute;
            right: 4px;
            top: 4px;
        }

        .hljs:hover > .clipboard-btn {
            display: inline;
        }

        .hljs > figcaption > .clipboard-btn {
            margin-right: 4px;
        }
    </style>
    <script>
      $(document).ready(function () {
        $('figure.hljs').each(function(i, figure) {
          var codeId = 'code-' + i;
          var code = figure.querySelector('.code');
          var copyButton = $('<button>Copy <i class="far fa-clipboard"></i></button>');
          code.id = codeId;
          copyButton.addClass('clipboard-btn');
          copyButton.attr('data-clipboard-target-id', codeId);

          var figcaption = figure.querySelector('figcaption');

          if (figcaption) {
            figcaption.append(copyButton[0]);
          } else {
            figure.prepend(copyButton[0]);
          }
        })

        var clipboard = new ClipboardJS('.clipboard-btn', {
          target: function(trigger) {
            return document.getElementById(trigger.getAttribute('data-clipboard-target-id'));
          }
        });
        clipboard.on('success', function(e) {
          e.clearSelection();
        })
      })
    </script>

    
    

    



<script src="/js/script.js"></script>


    
    <div class="searchbox ins-search">
    <div class="searchbox-mask"></div>
    <div class="searchbox-container ins-search-container">
        <div class="searchbox-input-wrapper">
            <input type="text" class="searchbox-input ins-search-input" placeholder="站内搜索" />
            <span class="searchbox-close ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="searchbox-result-wrapper ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
    (function (window) {
        var INSIGHT_CONFIG = {
            TRANSLATION: {
                POSTS: '文章',
                PAGES: '页面',
                CATEGORIES: '分类',
                TAGS: '标签',
                UNTITLED: '(无标题)',
            },
            CONTENT_URL: '/content.zh-cn.json',
        };
        window.INSIGHT_CONFIG = INSIGHT_CONFIG;
    })(window);
</script>

<script src="/js/insight.js"></script>

    
</body>
</html>